package org.mics.lang.security;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;

/**
 * 密码工具类
 * @author mics
 * @date 2020年6月10日
 * @version  1.0
 */
public class EncryptUtil {
	
	/**
	 * AES加密的密钥长度
	 */
	private static final int AES_KEY_LENGTH = 16;

    /**
     * AES加密ss
     * @param source 源数据
     * @param key 密钥
     * @return 加密结果
     */
    public static String aesEncrypt(String source, String key)  {
        if (StringUtils.isBlank(key)) {
            throw new SecurityException("publicKey不能为空");
        }
        if (key.length() != AES_KEY_LENGTH) {
            throw new SecurityException("key格式不正确");
        }
        byte[] raw = new byte[1024];
        try {
            raw = key.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            // 算法/模式/补码方式
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(source.getBytes("utf-8"));
            // 此处使用BASE64做转码功能
            return new String(Base64.getEncoder().encode(encrypted));
        }catch (UnsupportedEncodingException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
            throw new SecurityException("AES加密异常",e);
        }
    }


    /**
     * AES解密
     * @param source AES加密源数据
     * @param key 密钥
     * @return  解密之后结果
     */
    public static String aesDecrypt(String source, String key){
        // 判断Key是否正确
        if (key == null) {
            throw new SecurityException("privateKey不能为空");
        }
        if (key.length() != AES_KEY_LENGTH) {
            throw new SecurityException("key格式不正确");
        }
        try {
            byte[] raw = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            // 先用base64解密
            byte[] decodeResult = Base64.getDecoder().decode(source);
            byte[] original = cipher.doFinal(decodeResult);
            return new String(original,StandardCharsets.UTF_8);
        }catch (Exception e) {
            throw new SecurityException("AES解密异常",e);
        }

    }

    /**
     * 生成加密秘钥
     * @return
     */
    public static String getAesKey(String key) throws Exception {
        // 返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        // AES 要求密钥长度为 128
        kg.init(128, new SecureRandom(key.getBytes()));
        // 生成一个密钥
        SecretKey secretKey = kg.generateKey();
        return Hex.encodeHexString(secretKey.getEncoded()).substring(0,16);
    }

    /**
     * 根据key字符串生成公钥和私钥
     * @author mics
     * @date 2022-8-19
     * @version  1.0
     * @param key 密钥字符串
     * @return 公钥和私钥
     */
    public static Map<String, String> initKey(String key)  {
        //获得对象 KeyPairGenerator 参数 RSA 1024个字节
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            throw  new SecurityException("密钥管理器获取错误");
        }
        keyPairGen.initialize(1024,new SecureRandom(key.getBytes(StandardCharsets.UTF_8)));
        //通过对象 KeyPairGenerator 获取对象KeyPair
        KeyPair keyPair = keyPairGen.generateKeyPair();

        //通过对象 KeyPair 获取RSA公钥对象RSAPublicKey
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());

        //通过对象 KeyPair 获取RSA私钥对象RSAPrivateKey
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        //公私钥对象存入map中
        Map<String, String> keyMap = new HashMap<String, String>(2);
        keyMap.put("publicKey", publicKeyString);
        keyMap.put("privateKey", privateKeyString);
        return keyMap;
    }

    /**
     * RSA公钥加密
     * @param source 需要加密源字符串
     * @param publicKey 公钥
     * @return 密文
     */
    public static String rsaEncrypt(String source, String publicKey) {
        if (StringUtils.isBlank(source)) {
            throw  new SecurityException("需要加密源字符串不能为空");
        }
        if (StringUtils.isBlank(publicKey)) {
            throw  new SecurityException("publicKey不能为空");
        }
        try {
            byte[] decoded = Base64.getDecoder().decode(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] encrptyByte = cipher.doFinal(source.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(encrptyByte);
        }catch (Exception e) {
            throw  new SecurityException("rsa加密失败");
        }

    }

    /**
     * RSA私钥解密
     * @param source 需要解密源数据
     * @param privateKey 私钥
     * @return 明文
     */
    public static String rsaDecrypt(String source, String privateKey) {
        if (StringUtils.isBlank(source)) {
            throw  new SecurityException("需要解密源字符串不能为空");
        }
        if (StringUtils.isBlank(privateKey)) {
            throw  new SecurityException("privateKey不能为空");
        }
        try {
            //64位解码加密后的字符串
            byte[] inputByte = Base64.getDecoder().decode(source.getBytes("UTF-8"));
            //base64编码的私钥
            byte[] decoded = Base64.getDecoder().decode(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            String outStr = new String(cipher.doFinal(inputByte));
            return outStr;
        }catch (Exception e) {
            throw new SecurityException("rsa解密失败");
        }

    }



/*    public static void main(String[] args) {
        Map<String, String> result = initKey("456");
        String publicKey = result.get("publicKey");
        String privateKey = result.get("privateKey");
        String encrptyStr = RSAEncrypt("hello",publicKey);
        System.out.println(encrptyStr);
        System.out.println(RSADecrypt(encrptyStr,privateKey));
    }*/

}
